package com.huangfu.learning.javabase.common.utils;


import org.apache.commons.codec.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * Author: huangfu.daohui
 * Date: 2018/7/30
 * Time: 10:30
 * Version: 1.0
 * Description: 阿里云工具类
 * huangfu：AccessKey ID：LTAIZ4fXHJUiJzTK	  Access Key Secret：FVbZX7ABCcqjTGbw79DhILWL9LTo3I   青岛
 * company:AccessKey ID：LTAIbO9FPYfXe7jX	  Access Key Secret：8NmNnBRBGdSPbDKeuSxrz432Jfhyhi   杭州
 **/
public class AliyunUtils {
    private static final String ENCODING = "UTF-8";

    private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    // 规范化请求字符串
    public static String percentEncode(String value) throws UnsupportedEncodingException {
        return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null;
    }

    // 预定义编码时间格式
    public static String formatIso8601Date(Date date) {
        SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
        df.setTimeZone(new SimpleTimeZone(0, "GMT"));
        String dateString = "";
        return df.format(date);
    }

    //构造请求
    public static String structureStringToSign() {
        final String HTTP_METHOD = "GET";
        Map parameters = new HashMap();
        // 输入请求参数
        parameters.put("Action", "DescribeRegions");
        parameters.put("Version", "2014-05-26");
        parameters.put("AccessKeyId", "LTAIZ4fXHJUiJzTK");
        parameters.put("Timestamp", formatIso8601Date(new Date()));
        parameters.put("SignatureMethod", "HMAC-SHA1");
        parameters.put("SignatureVersion", "1.0");
        parameters.put("SignatureNonce", UUID.randomUUID().toString());
        parameters.put("Format", "XML");
        // 排序请求参数
        String[] sortedKeys = (String[]) parameters.keySet().toArray(new String[]{});
        Arrays.sort(sortedKeys);
        final String SEPARATOR = "&";
        // 构造 stringToSign 字符串
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append(HTTP_METHOD).append(SEPARATOR);
        try {
            stringToSign.append(percentEncode("/")).append(SEPARATOR);
            StringBuilder canonicalizedQueryString = new StringBuilder();
            for (String key : sortedKeys) {
                // 这里注意编码 key 和 value
                canonicalizedQueryString.append("&")
                        .append(percentEncode(key)).append("=")
                        .append(percentEncode(parameters.get(key).toString()));
            }
            // 这里注意编码 canonicalizedQueryString
            stringToSign.append(percentEncode(
                    canonicalizedQueryString.toString().substring(1)));

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return stringToSign.toString();
    }

    // 签名
    public static String signature() {
        String stringToSign = structureStringToSign();
        // 以下是一段计算签名的示例代码
        final String ALGORITHM = "HmacSHA1";
        final String ENCODING = "UTF-8";
        String key = "FVbZX7ABCcqjTGbw79DhILWL9LTo3I&";
        String signature = "";
        Mac mac = null;
        try {
            mac = Mac.getInstance(ALGORITHM);
            mac.init(new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM));
            byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING));
            signature = percentEncode(new String(Base64.encodeBase64(signData)));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return signature;
    }

    public static void main(String[] args) {
        System.out.println("structureRequestString:" + structureStringToSign());
        System.out.println("signature:" + signature());
        try {
            System.out.println(formatIso8601Date(new Date()).toString());
            System.out.println(percentEncode(formatIso8601Date(new Date()).toString()));

            System.out.println((percentEncode("huang fu+dao&hui=")));
            System.out.println(percentEncode(percentEncode("huang fu+dao&hui=")));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

    }
}
